package com.yueyang.sojourn.server.service.sojourn.pay;

import com.alibaba.fastjson.JSON;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.profitsharing.*;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.ProfitSharingService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.yueyang.sojourn.server.config.WxPayProperties;
import com.yueyang.sojourn.server.model.enums.OrderTypeEnum;
import com.yueyang.sojourn.server.model.enums.PayConstants;
import com.yueyang.sojourn.server.model.enums.ShareConstans;
import com.yueyang.sojourn.server.model.po.*;
import com.yueyang.sojourn.server.service.sojourn.merch.SojournMerchService;
import com.yueyang.sojourn.server.service.sojourn.merchant.SojournMerchantService;
import com.yueyang.sojourn.server.service.sojourn.order.SojournOrderRefundService;
import com.yueyang.sojourn.server.service.sojourn.order.SojournOrderService;
import com.yueyang.sojourn.server.service.sojourn.projectshare.SojournProjectShareService;
import com.yueyang.sojourn.server.service.sojourn.sequence.SojournSequnceManager;
import com.yueyang.sojourn.server.service.sojourn.share.SojournShareDetailService;
import com.yueyang.sojourn.server.service.sojourn.share.SojournShareService;
import com.yueyang.sojourn.server.service.sojourn.transaction.SojournTransactionService;
import com.yueyang.uc.model.UcLoginUserV1;
import com.yueyang.uc.model.UcUserV1;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 支付
 * @author Andy.yang
 * @version v1
 * @summary
 * @Copyright (c) 2019, YueYang Group All Rights Reserved.
 * @since 2020/3/25
 */
@Slf4j
@Service
public class PayServiceWill {
    @Autowired
    WxPayService wxPayService;
    @Autowired
    ProfitSharingService profitSharingService;
    @Autowired
    SojournTransactionService transactionService;
    @Autowired
    SojournOrderService orderService;
    @Autowired
    SojournMerchantService merchantService;
    @Autowired
    WxPayProperties wxPayProperties;
    @Autowired
    SojournProjectShareService projectShareService;
    @Autowired
    SojournMerchService merchService;
    @Autowired
    SojournShareService shareService;
    @Autowired
    SojournShareDetailService shareDetailService;
    @Autowired
    SojournOrderRefundService orderRefundService;
    @Autowired
    SojournSequnceManager sequnceManager;

    /**
     * 《一》：微信预支会订单
     * 1: 必须保证幂等
     *
     * 本方法实现：
     * 2：生成微信预支付订单（指明分账标识）
     * 3：生成本地交易（残缺）
     * 4：返回给小程序，让小程序进行直接对微信账号支付；
     *
     * 后续支付结果：
     * 5：回调或主动查询（根据残缺交易）获取支付结果
     * 6：补全 本地交易（残缺）、同步更新订单状态、同步库存
     * @param orderId 本地订单
     * @param needShare 是否需要分账
     * @return 微信预支付id
     */
    @Transactional
    public WxPayMpOrderResult prepay(Long orderId, String ip, boolean needShare, UcLoginUserV1 user) {
        BigDecimal price = new BigDecimal(0.01);
        WxPayMpOrderResult result = null;
        try {
            SojournOrder order = orderService.findById(orderId);
            price = order.getTotalPrice();

            SojournMerchant merchant = null;
            WxPayUnifiedOrderRequest orderRequest = null;
            //会员订单：直接付给平台；
            if(OrderTypeEnum.VIP.getCode() == order.getType()){
                //商户拥有者：平台
                String platformSubMchId = wxPayProperties.getPlatformSubMchId();
                String platformSubMchName = wxPayProperties.getPlatformSubMchName();
                merchant = new SojournMerchant();
                merchant.setId(-2L);//规定-2是平台自营子商户的虚拟id;-1是平台虚拟id
                merchant.setName(platformSubMchName);
                merchant.setWxMerchantNo(platformSubMchId);

                //拼装微信预支付请求参数
                orderRequest = new WxPayUnifiedOrderRequest();
                orderRequest.setOutTradeNo(order.getSn());
                orderRequest.setSubOpenid(user.getLoginWechatOpenId());//服务商模式下，改为subOpenId
                orderRequest.setBody("购买：" + order.getMerchTitle());//服务商模式下，改为subOpenId
//                orderRequest.setProfitSharing(needShare ? "Y" : "N");//先打个标识，冻结支付：是否需要分账标识; 直付不需要分账
                orderRequest.setSubMchId(platformSubMchId);//钱支付给子服务商

                // 订单总金额：元转成分
                orderRequest.setTotalFee(convertYuan2Fen(order.getTotalPrice()));
                orderRequest.setSpbillCreateIp(ip);
            }
            //合作商户支付：任何合作商商品--平台必须制成；（逻辑：平台写死商户号；平台分成由商户分成剩余部分）
            else if(OrderTypeEnum.MERCH.getCode() == order.getType()){
                //商户拥有者：平台合作商户
                merchant = merchantService.findByProjectId(order.getMerchProjectId());
                //拼装微信预支付请求参数
                orderRequest = new WxPayUnifiedOrderRequest();
                orderRequest.setOutTradeNo(order.getSn());
                orderRequest.setSubOpenid(user.getLoginWechatOpenId());
                orderRequest.setBody("购买：" + order.getMerchTitle());//服务商模式下，改为subOpenId
                orderRequest.setProfitSharing(needShare ? "Y" : "N");//先打个标识，冻结支付：是否需要分账标识
                orderRequest.setSubMchId(merchant.getWxMerchantNo());//钱支付给子服务商
                // 订单总金额：元转成分
                orderRequest.setTotalFee(convertYuan2Fen(order.getTotalPrice()));
                orderRequest.setSpbillCreateIp(ip);
            }

            try {
                result = wxPayService.createOrder(orderRequest);
            }catch (Exception e){
                // todo 记录日志
                throw  new RuntimeException(e);
            }


            //缓存prepayID用于后续模版通知
            String prepayId = result.getPackageValue();
            prepayId = prepayId.replace("prepay_id=", "");

            //创建残缺交易
            SojournTransaction transaction = transactionService.findPayByOrderSn(order.getSn());
            if(transaction == null) {
                transaction = new SojournTransaction();
                transaction.setTotalFee(orderRequest.getTotalFee());
                transaction.setThirdPrepayId(prepayId);
                transaction.setOrderSn(order.getSn());
                transaction.setStatus(PayConstants.TransactionStatusEnum.PAYING.getCode());
                transaction.setDesc(orderRequest.getBody());

                //付款方信息：
                transaction.setPayerId(user.getId());
                transaction.setPayerName(user.getNickName());
                transaction.setPayerThirdNo(user.getLoginWechatOpenId());
                transaction.setPayerType(PayConstants.ThirdPayAccountTypeEnum.WX_PERSONAL_OPENID.getCode());
                //收款方信息
                transaction.setRemitteeId(merchant.getId());
                transaction.setRemitteeName(merchant.getName());
                transaction.setRemitteeType(PayConstants.ThirdPayAccountTypeEnum.WX_MERCHANT.getCode());
                transaction.setRemitteeThirdNo(merchant.getWxMerchantNo());
                transaction.setType(1);//1-付款 2-退款
                transaction.setChannelType(1); //1-微信
                transaction.setCreator(user.getId());

                //当前到预支付
//            transaction.setStep(PayStepEnum.PREPAY.getCode());
                if(transactionService.add(transaction) <= 0){
                    log.error("订单id[" + orderId + "]创建预支付交易失败");
                    throw new RuntimeException("");
                }
            }else{
                transaction.setUpdator(user.getId());
                transaction.setThirdPrepayId(prepayId);
                transactionService.updateThirdPrepayId(transaction);
            }
            //todo 支付日志
            return result;
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage(),e);
            //todo 支付日志
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据本地交易 查询微信支付情况
     * @param transaction
     * @return
     */
    public WxPayOrderQueryResult queryOrder(SojournTransaction transaction) {
        BigDecimal price = new BigDecimal(0.1);
        WxPayOrderQueryResult result = null;
        try {
            //拼装微信请求参数
            WxPayOrderQueryRequest orderRequest = new WxPayOrderQueryRequest();
            orderRequest.setOutTradeNo(transaction.getOrderSn());
            orderRequest.setSubMchId(transaction.getRemitteeThirdNo());//钱支付给子服务商: 这个子商户的订单

            result = wxPayService.queryOrder(orderRequest);

            if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getResultCode())){
//                logger.error(xmlResult); todo 记录日志
                throw new WxPayException("微信订单支付结果查询失败！");
            }
            if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getReturnCode())){
//                logger.error(xmlResult); todo 记录日志
                throw new WxPayException("微信订单支付结果查询失败！");
            }
            return result;
            //todo 记录日志
        }catch (Exception e){
            log.error(e.getMessage(),e);
            //todo 记录日志
            throw new RuntimeException(e.getMessage(),e);
        }
    }

    /**
     * 《二》： 更新支付结果
     * @param orderPayResult
     * @return
     */
    @Transactional
    public boolean paid(WxPayOrderQueryResult orderPayResult) {
        if(!PayConstants.TradeStateEnum.SUCCESS.getCode().equals(orderPayResult.getTradeState())){
            return false;
        }
        String sn = orderPayResult.getOutTradeNo();
        //查询交易
        SojournTransaction transaction = transactionService.findPayByOrderSn(sn);
        if(PayConstants.TransactionStatusEnum.PAYING.getCode() != transaction.getStatus()){
            return false;
        }

        //更新交易状态
        transaction.setStatus(PayConstants.TransactionStatusEnum.PAID.getCode());
        transaction.setThirdTransId(orderPayResult.getTransactionId());
//        transaction.setStep();
        Long userId = transaction.getUpdator() == null || transaction.getUpdator() <=0 ? transaction.getCreator() : transaction.getUpdator();
        transaction.setUpdator(userId);
        transactionService.update(transaction);

        //更新订单状态
        SojournOrder order = orderService.findByOrderSn(sn);
        //如果是vip直接成交
        if(order.getType() == OrderTypeEnum.VIP.getCode()) {
            orderService.updatePaidAndDealed(order.getId(), userId);
        }else{ //否则为支付
            orderService.updatePaid(order.getId(),userId);
        }

        //日志 todo
        return true;
    }


    /**
     * 商户管理中：只要新增一个商户就加入一个商户，至到成功
     * 增加分账方:一次一个；预先设置，只有设置成功的，分账时指定的分账商户才可以分账；
     *
     * 没有查询成功的接口；所以只要没有设置成功，就不停的设置
     *
     * MERCHANT_ID：商户ID
     * PERSONAL_WECHATID： 个人微信号
     * PERSONAL_OPENID：个人openid（由父商户APPID转换得到）
     * PERSONAL_SUB_OPENID: 个人sub_openid（由子商户APPID转换得到）
     *
     * 本字段值为枚举：
     * SERVICE_PROVIDER：服务商
     * STORE：门店
     * STAFF：员工
     * STORE_OWNER：店主
     * PARTNER：合作伙伴
     * HEADQUARTER：总部
     * BRAND：品牌方
     * DISTRIBUTOR：分销商
     * USER：用户
     * SUPPLIER：供应商
     * CUSTOM：自定义
     */
    public ProfitSharingReceiverResult addWxShareReceiver(SojournProjectShare share) throws WxPayException {
        return addWxShareReceiver(share.getProjectId(),share.getReceiverId(),share.getReceiverType(),share.getRelationType());
    }

    /**
     * 商户管理中：只要新增一个商户就加入一个商户，至到成功
     * 增加分账方:一次一个；预先设置，只有设置成功的，分账时指定的分账商户才可以分账；
     *
     * 没有查询成功的接口；所以只要没有设置成功，就不停的设置
     *
     * MERCHANT_ID：商户ID
     * PERSONAL_WECHATID： 个人微信号
     * PERSONAL_OPENID：个人openid（由父商户APPID转换得到）
     * PERSONAL_SUB_OPENID: 个人sub_openid（由子商户APPID转换得到）
     *
     * 本字段值为枚举：
     * SERVICE_PROVIDER：服务商
     * STORE：门店
     * STAFF：员工
     * STORE_OWNER：店主
     * PARTNER：合作伙伴
     * HEADQUARTER：总部
     * BRAND：品牌方
     * DISTRIBUTOR：分销商
     * USER：用户
     * SUPPLIER：供应商
     * CUSTOM：自定义
     */
    public ProfitSharingReceiverResult addWxShareReceiver(Long projectId,Long receiverId,String receiverType,String relationType) throws WxPayException {
        //1：设置接收方
//        String receiverType = share.getReceiverType();//接收方类型
//        String relationType = share.getRelationType();

        SojournMerchant merchantReceiver = merchantService.findById(receiverId);
        // 设置微信分账方 -- 创建分账方时就需要设置
        Receiver receiver = new Receiver(receiverType,
                merchantReceiver.getWxMerchantNo(),
                merchantReceiver.getName(),
                relationType,
                null);

        //2：设置当前项目子商户 - 接收方配置在当前子商户下
        SojournMerchant merchantOwner = merchantService.findByProjectId(projectId);
        ProfitSharingReceiverRequest receiverRequest = ProfitSharingReceiverRequest
                .newBuilder()
                .receiver(receiver.toJSONString())
                .build();
        receiverRequest.setSubMchId(merchantOwner.getWxMerchantNo());//当前分账方设置到此子商户号下

        //3：执行
        ProfitSharingReceiverResult result = profitSharingService.addReceiver(receiverRequest);

        if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getResultCode())){
//                logger.error(xmlResult);
            throw new WxPayException("微信增加分账账户失败！");
        }
        if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getReturnCode())){
//                logger.error(xmlResult);
            throw new WxPayException("微信增加分账账户失败！");
        }
        return result;
    }

    /**
     * 关闭微信订单
     * @param transaction
     * @return
     * @throws WxPayException
     */
    public WxPayOrderCloseResult closeOrder(SojournTransaction transaction) throws WxPayException {
        WxPayOrderCloseRequest request = WxPayOrderCloseRequest.newBuilder().build();
        request.setOutTradeNo(transaction.getOrderSn());
        if(PayConstants.ThirdPayAccountTypeEnum.WX_MERCHANT.getCode().equals(transaction.getRemitteeType())){
            request.setSubMchId(transaction.getRemitteeThirdNo());
        }
        WxPayOrderCloseResult rs = wxPayService.closeOrder(request);
        return rs;
    }

    /**
     * 商户管理中：只要新增一个商户就加入一个商户，至到成功
     * 增加分账方:一次一个；预先设置，只有设置成功的，分账时指定的分账商户才可以分账；
     *
     * 没有查询成功的接口；所以只要没有设置成功，就不停的设置
     *
     * MERCHANT_ID：商户ID
     * PERSONAL_WECHATID： 个人微信号
     * PERSONAL_OPENID：个人openid（由父商户APPID转换得到）
     * PERSONAL_SUB_OPENID: 个人sub_openid（由子商户APPID转换得到）
     *
     * 本字段值为枚举：
     * SERVICE_PROVIDER：服务商
     * STORE：门店
     * STAFF：员工
     * STORE_OWNER：店主
     * PARTNER：合作伙伴
     * HEADQUARTER：总部
     * BRAND：品牌方
     * DISTRIBUTOR：分销商
     * USER：用户
     * SUPPLIER：供应商
     * CUSTOM：自定义
     */
    public ProfitSharingReceiverResult removeWxShareReceiver(SojournProjectShare share) throws WxPayException {
        //1：设置接收方
        String receiverType = share.getReceiverType();//接收方类型
        String relationType = share.getRelationType();

        SojournMerchant merchantReceiver = merchantService.findById(share.getReceiverId());
        // 设置微信分账方 -- 创建分账方时就需要设置
        Receiver receiver = new Receiver(receiverType,
                merchantReceiver.getWxMerchantNo(),
                merchantReceiver.getName(),
                relationType,
                null);

        //2：设置当前项目子商户 - 接收方配置在当前子商户下
        SojournMerchant merchantOwner = merchantService.findByProjectId(share.getProjectId());
        ProfitSharingReceiverRequest receiverRequest = ProfitSharingReceiverRequest
                .newBuilder()
                .receiver(receiver.toJSONString())
                .build();
        receiverRequest.setSubMchId(merchantOwner.getWxMerchantNo());//当前分账方设置到此子商户号下

        //3：执行
        ProfitSharingReceiverResult result = profitSharingService.removeReceiver(receiverRequest);
        return result;
    }

    /**
     * 《三》：增加分账方:一次一个；　一直重试至到成功
     */
    public ProfitSharingReceiverResult addWxPlatformShareReceiver(String merchatWxNo) throws WxPayException {
        //3：设置微信分账方
        ProfitSharingReceiverRequest receiverRequest = ProfitSharingReceiverRequest.newBuilder().build();
        Map<String,Object> receiver = new HashMap<>();
//        MERCHANT_ID：商户ID
//        PERSONAL_WECHATID：个人微信号 PERSONAL_OPENID：个人openid（由父商户APPID转换得到）PERSONAL_SUB_OPENID: 个人sub_openid（由子商户APPID转换得到）

        //服务商：
        receiver.put("type","MERCHANT_ID");
        receiver.put("name",wxPayProperties.getMchName());
        receiver.put("account",wxPayProperties.getMchId());
        receiver.put("relation_type","SERVICE_PROVIDER");
        receiverRequest.setReceiver(JSON.toJSONString(receiver));
        receiverRequest.setSubMchId(merchatWxNo);
        ProfitSharingReceiverResult result = profitSharingService.addReceiver(receiverRequest);

        if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getResultCode())){
//                logger.error(xmlResult);
            throw new WxPayException("微信增加分账账户失败！");
        }
        if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getReturnCode())){
//                logger.error(xmlResult);
            throw new WxPayException("微信增加分账账户失败！");
        }
        return result;
    }

    /**
     * 开始单次分账
     * @param share 分账单
     */
    public ProfitSharingResult shareOne(SojournShare share) throws WxPayException {
        SojournOrder order = orderService.findById(share.getOrderId());
        List<SojournShareDetail> details = shareDetailService.findByShareId(share.getId());
        ReceiverList instance = ReceiverList.getInstance();
        for(SojournShareDetail detail : details){
            if(!detail.getPrime()) {
                instance.add(new Receiver(WxPayConstants.ReceiverType.MERCHANT_ID,
                        detail.getReceiverThirdNo(),
                        detail.getFee(),
                        "分账：" + order.getMerchTitle()));
                //分账前增加分账方:如果当前是平台
                if(detail.getReceiverThirdNo().equals(wxPayProperties.getMchId())) {
                    addWxPlatformShareReceiver(share.getThirdMerchantNo());
                }else{
                    SojournProjectShare projectShare = projectShareService.findById(detail.getReceiverId());
                    addWxShareReceiver(projectShare);
                }
            }
        }
        //30000002922019102310811092093
        ProfitSharingRequest request = ProfitSharingRequest
                .newBuilder()
                .outOrderNo(share.getSn())
                .transactionId(share.getThirdTransactionId())
                .receivers(instance.toJSONString())
                .build();
        request.setSubMchId(share.getThirdMerchantNo());//当前分账方设置到此子商户号下

        ProfitSharingResult result = profitSharingService.profitSharing(request);

        //分账成功--同步更新分账单状态 todo
        if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getResultCode())){
//                logger.error(xmlResult);
            throw new WxPayException("微信分账失败！");
        }
        if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getReturnCode())){
//                logger.error(xmlResult);
            throw new WxPayException("微信分账失败！");
        }
        share.setStatus(ShareConstans.ShareStatusEnum.SHARED.getCode());
        share.setUpdator(-1L);
        share.setThirdShareId(result.getOrderId());
        shareService.updateThirdShareIdAndStatus(share);
        return result;
    }

    /**
     * 结算分账
     */
    public void submitShare(String transId) throws WxPayException {
        ProfitSharingFinishRequest request = ProfitSharingFinishRequest.newBuilder().build();
        request.setOutOrderNo("finish_" + transId);//分账单号
        request.setTransactionId(transId);
        ProfitSharingResult result = profitSharingService.profitSharingFinish(request);

        //todo 记录日志

    }

    /**
     * 分账结果：失败重试
     */
    public ProfitSharingQueryResult queryFinish(String transId) throws WxPayException {
        ProfitSharingQueryRequest request = ProfitSharingQueryRequest.newBuilder().build();
        request.setOutOrderNo("finish_" + transId);//分账单号
        request.setTransactionId(transId);
        ProfitSharingQueryResult result = profitSharingService.profitSharingQuery(request);
        return result;
    }


    /**
     * 订单退款
     * @param refundId 退款单id
     * @return
     */
    public WxPayRefundResult refund(Long refundId,UcUserV1 loginUser) {
        SojournOrderRefund refund = orderRefundService.findById(refundId);
        SojournOrder order = orderService.findById(refund.getOrderId());
        SojournMerchant merchant = merchantService.findByProjectId(order.getMerchProjectId());

        //先创建一个退款交易(一个交易同一时间只允许一个正在退款状态)
        SojournTransaction transactionRefund = transactionService.findRefundByOrderRefundSn(refund.getSn());
        if(transactionRefund == null){
            SojournTransaction transactionPay = transactionService.findPayByOrderSn(order.getSn());
            transactionRefund = new SojournTransaction();
            transactionRefund.setType(PayConstants.TransactionTypeEnum.REFUND.getCode());//退款
            transactionRefund.setChannelType(transactionPay.getChannelType());
            transactionRefund.setStatus(PayConstants.TransactionStatusEnum.REFUNDING.getCode());
            transactionRefund.setRelationId(transactionPay.getId());//退款对应的支付订单的id
            //收付款方互换
            transactionRefund.setPayerId(transactionPay.getRemitteeId());
            transactionRefund.setPayerName(transactionPay.getRemitteeName());
            transactionRefund.setPayerType(transactionPay.getRemitteeType());
            transactionRefund.setPayerThirdNo(transactionPay.getRemitteeThirdNo());
            transactionRefund.setRemitteeId(transactionPay.getPayerId());
            transactionRefund.setRemitteeName(transactionPay.getPayerName());
            transactionRefund.setRemitteeType(transactionPay.getPayerType());
            transactionRefund.setRemitteeThirdNo(transactionPay.getPayerThirdNo());

            transactionRefund.setOrderSn(transactionPay.getOrderSn());
            transactionRefund.setRefundSn(refund.getSn());
            transactionRefund.setTotalFee(transactionPay.getTotalFee());
            transactionRefund.setCreator(-1L);
            transactionService.add(transactionRefund);
        }

        WxPayRefundRequest wxRequest = null;
        if(OrderTypeEnum.VIP.getCode() == order.getType()){
            wxRequest = WxPayRefundRequest.newBuilder().build();
            wxRequest.setTotalFee(convertYuan2Fen(order.getTotalPrice()));
            wxRequest.setOutTradeNo(order.getSn());
            wxRequest.setRefundFee(wxRequest.getTotalFee());
            wxRequest.setOutRefundNo(transactionRefund.getRefundSn());
        }else if(OrderTypeEnum.MERCH.getCode() == order.getType()){
            wxRequest = WxPayRefundRequest.newBuilder().build();
            wxRequest.setTotalFee(convertYuan2Fen(order.getTotalPrice()));
            wxRequest.setOutTradeNo(order.getSn());
            wxRequest.setRefundFee(wxRequest.getTotalFee());
            wxRequest.setOutRefundNo(transactionRefund.getRefundSn());
            wxRequest.setSubMchId(merchant.getWxMerchantNo());//子商户的商户号
        }

        //执行
        WxPayRefundResult result = null;
        try {
            result = wxPayService.refund(wxRequest);
            refundResultOperate(transactionRefund.getRefundSn(),result.getRefundId());
        } catch (WxPayException e) {
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 订单退款结果查询
     * @param orderRefundSn  退款单号
     * @return
     */
    public WxPayRefundQueryResult refundQuery(String orderRefundSn) throws WxPayException {
        SojournTransaction transaction = transactionService.findRefundByOrderRefundSn(orderRefundSn);
        SojournOrder order = orderService.findByOrderSn(transaction.getOrderSn());
        if(order == null){
            return null;
        }
        WxPayRefundQueryRequest wxRequest = WxPayRefundQueryRequest.newBuilder().build();
//        wxRequest.setOutTradeNo(orderSn);
        wxRequest.setOutRefundNo(orderRefundSn);
        if(OrderTypeEnum.MERCH.getCode() == order.getType()){
            SojournMerchant merchant = merchantService.findByProjectId(order.getMerchProjectId());
            wxRequest.setSubMchId(merchant.getWxMerchantNo());//子商户的商户号
        }

        //执行
        WxPayRefundQueryResult result = null;
        try {
            result = wxPayService.refundQuery(wxRequest);
        }catch (WxPayException e){
            if("REFUNDNOTEXIST".equals(e.getErrCode())){
                updateRefundNotExist(orderRefundSn);
            }
            throw e;
        }
        if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getResultCode())){
//                logger.error(xmlResult);
            throw new WxPayException("微信查询退款结果失败！");
        }
        if(!WxPayConstants.ResultCode.SUCCESS.equals(result.getReturnCode())){
//                logger.error(xmlResult);
            throw new WxPayException("微信查询退款结果失败！");
        }
        return result;
    }

    /**
     * 退款不存在时，更新本地退款为关闭状态
     * @return
     */
    public boolean updateRefundNotExist(String orderRefundSn){
        SojournTransaction transaction = transactionService.findRefundByOrderRefundSn(orderRefundSn);
        transaction.setStatus(PayConstants.TransactionStatusEnum.CLOSED_REFUND_NOT_EXISTS.getCode());
        transaction.setUpdator(-1L);
        transactionService.update(transaction);
        return true;
    }
    /**
     * 订单退款成功结果处理
     * @param orderRefundSn 退款单号
     * @return
     */
    @Transactional
    public boolean refundResultOperate(String orderRefundSn,String thirdRefundId) {
//        SojournOrder order = orderService.findByOrderRefundSn(orderRefundSn);
//        if(OrderTypeEnum.VIP.getCode() == order.getType()){
//            wxRequest = WxPayRefundRequest.newBuilder().build();
//            wxRequest.setTotalFee(convertYuan2Fen(order.getTotalPrice()));
//            wxRequest.setOutTradeNo(order.getSn());
//            wxRequest.setRefundFee(wxRequest.getTotalFee());
//            wxRequest.setOutRefundNo("rf" + orderId.toString());
//        }else if(OrderTypeEnum.MERCH.getCode() == order.getType()){
//            wxRequest = WxPayRefundRequest.newBuilder().build();
//            wxRequest.setTotalFee(convertYuan2Fen(order.getTotalPrice()));
//            wxRequest.setOutTradeNo(order.getSn());
//            wxRequest.setRefundFee(wxRequest.getTotalFee());
//            wxRequest.setOutRefundNo("rf" + orderId.toString());
//            wxRequest.setSubMchId(merchant.getWxMerchantNo());//子商户的商户号
//        }
        SojournTransaction transaction = transactionService.findRefundByOrderRefundSn(orderRefundSn);
        if(transaction.getStatus() == PayConstants.TransactionStatusEnum.REFUNDED.getCode()){
            return false;
        }
        SojournOrder order = orderService.findByOrderSn(transaction.getOrderSn());
        //更新交易状态
        transaction.setStatus(PayConstants.TransactionStatusEnum.REFUNDED.getCode());
        transaction.setThirdTransId(thirdRefundId);
        transactionService.update(transaction);
        //更新订单状态
        orderService.updateRefunded(order.getId(),-1L);//-1代表系统处理
        //记录日志 todo

        return true;
    }

    /**
     * 元转分
     * @param yuan
     * @return
     */
    public Integer convertYuan2Fen(BigDecimal yuan){
        int fen = 0;
        BigDecimal actualPrice = yuan;
        fen = actualPrice.multiply(new BigDecimal(100)).intValue();
        return fen;
    }

}
